import { useEffect, useState } from 'react'
import { createFromIconfontCN } from '@ant-design/icons';
import { Menu } from 'antd';
import { Link } from 'react-router-dom'
import { useHistory } from 'react-router-dom'

import { DEFAULT_ICON_TYPE, LAST_SELECT_KEYS, LAST_OPEN_KEYS } from '@/constant/common/menu'

const IconFont = createFromIconfontCN({
  scriptUrl: '/font/iconfont.js',
});

const MenuTree = ({
  menus
}) => {
  const { SubMenu, Item } = Menu
  const [ openKeys, setOpenKeys ] = useState([])
  const [ selectedKey, setSelectedKey ] = useState([])

  const history = useHistory()

  const SPLIT = '-'

  // 前进、后退操作监听
  window.onpopstate = set
  useEffect(() => {
    set()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [history])

  return (
    <Menu theme="dark" mode="inline"
      selectedKeys={selectedKey}
      onSelect={menuSelectHandle}
      onOpenChange={openChangeHandle}
      openKeys={openKeys}
    >
      {
        getMenu(menus)
      }
    </Menu>
  )

  function getMenu(menus) {
    return menus.map((menu) => {
      return menu.childs ?
        <SubMenu key={menu.id} title={menu.name} icon={<IconFont type={menu.icon ? menu.icon : DEFAULT_ICON_TYPE} />} >
          {
            getMenu(menu.childs)
          }
        </SubMenu>
        :
        <Item key={menu.id} icon={<IconFont type={menu.icon ? menu.icon : DEFAULT_ICON_TYPE} />} >
          <Link to={menu.url}>
            {menu.name}
          </Link>
        </Item>
    });
  }

  // 菜单选中处理函数
  function menuSelectHandle({selectedKeys}) {
    setSelectedKey(selectedKeys)
    window.sessionStorage.setItem(LAST_SELECT_KEYS, selectedKeys.join(SPLIT))
  }

  // 展开菜单改变处理函数
  function openChangeHandle(openKeys) {
    setOpenKeys(openKeys)
    window.sessionStorage.setItem(LAST_OPEN_KEYS, openKeys.join(SPLIT))
  }

  function set() {
    // 如果是POP动作类型(F5刷新、地址栏输入、前进后退按钮等)
    if (history.action !== 'POP') {
      setBySessionStorage()
      return
    }
    // 获取目标地址
    const url = history.location.pathname
    // 获取目标菜单
    const resultMenu = findMenuByUrl(url)
    // 如果找到了对应的子菜单，就设置sessionStorage缓存
    if (resultMenu) {
      window.sessionStorage.setItem(LAST_SELECT_KEYS, resultMenu.id)
      window.sessionStorage.setItem(LAST_OPEN_KEYS, getAllParentByMenu(resultMenu).join(SPLIT))
    }
    // 最后根据sessionStorage设置显示
    setBySessionStorage()
  }

  // 根据sessionStorage设置菜单的展开项和选中项
  function setBySessionStorage() {
    const selectedKey = window.sessionStorage.getItem(LAST_SELECT_KEYS);
    selectedKey && setSelectedKey(selectedKey.split(SPLIT))
    const openKeys = window.sessionStorage.getItem(LAST_OPEN_KEYS);
    openKeys && setOpenKeys(openKeys.split(SPLIT))
  }

  // 循环匹配目标url
  function findMenuByUrl(url, parentMenu) {
    // debugger
    // 如果没有传入父菜单，就先开始遍历menus，有父菜单循环其下的子菜单
    const mainMenus = parentMenu ? parentMenu.childs : menus
    let resultMenu = null
    // 循环遍历
    for (const menu of mainMenus) {
      // console.log('menu', menu)
      // 设置parent属性，方便后续根据目标菜单获取所有的父菜单
      menu.parent = parentMenu || {}
      if (menu.url === url) {
        // 如果url匹配上，就跳出循环，返回
        resultMenu = menu
        break;
      }
      // 没有匹配上url就先判断该菜单是否有子菜单，如果有就遍历子菜单
      if (menu.childs && menu.childs.length > 0) {
        resultMenu = findMenuByUrl(url, menu)
        // 如果子菜单循环遍历获取到了目标结果，也跳出循环
        if (!resultMenu) break;
      }
    }
    return resultMenu
  }

  // 根据目标菜单获取所有的父菜单，一层层遍历
  function getAllParentByMenu(menu, result = []) {
    // 如果有父菜单就将url放入结果集中，并递归获取再上的父菜单
    if (menu.parent) {
      result.push(menu.parent.id)
      getAllParentByMenu(menu.parent, result)
    }
    return result
  }
}

export default MenuTree
